package com.newhope.trade.getway.integration.filter;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.poi.util.IOUtils;
import org.springframework.stereotype.Component;

@Component
@WebFilter(filterName="requestFilter", urlPatterns="/*")
public class RequestFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		MultiReadHttpServletRequest requestWrapper = new MultiReadHttpServletRequest((HttpServletRequest) request);
		chain.doFilter(requestWrapper, response);
	}

	@Override
	public void destroy() {
	}

	/**
	 * cacheable servlet request
	 * @author RDC-201
	 *
	 */
	private class MultiReadHttpServletRequest extends HttpServletRequestWrapper {

		private ByteArrayOutputStream cachedBytes;
		
		public MultiReadHttpServletRequest(HttpServletRequest request) {
			super(request);
		}

		@Override
		public ServletInputStream getInputStream() throws IOException {
			if (cachedBytes == null)
				cacheInputStream();
			return new CachedServletInputStream();
		}

		@Override
		public BufferedReader getReader() throws IOException {
			return new BufferedReader(new InputStreamReader(getInputStream()));
		}
		
		private void cacheInputStream() throws IOException {
			cachedBytes = new ByteArrayOutputStream();
			IOUtils.copy(super.getInputStream(), cachedBytes);
		}
		
		private class CachedServletInputStream extends ServletInputStream {
		    private ByteArrayInputStream input;

		    public CachedServletInputStream() {
		    	input = new ByteArrayInputStream(cachedBytes.toByteArray());
		    }
		    
		    @Override
			public int read() throws IOException {
				return input.read();
			}
		    
			@Override
			public boolean isFinished() {
				return false;
			}

			@Override
			public boolean isReady() {
				return false;
			}

			@Override
			public void setReadListener(ReadListener listener) {
			}
		  }
	}
}
